﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace 锁
{
    /**
     *  悲观锁的使用
     *  EF 不支持悲观锁，只能写原生 SQL。
     *  一定要在同一个事务中。在查询语句的表名后加上 with (xlock,ROWLOCK)。xlock 表示“排
     *  他锁”，一旦加上排他锁，那么其他人再获得这个锁的话就要等待开锁（事务结束）。
     *  ROWLOCK 为行锁，为锁定查询出来的行。
     */
    class Program
    {
        static void Main(string[] args)
        {
            //Console.WriteLine("请输入您的名字");
            //string myname = Console.ReadLine();
            //string connstr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;

            //using (SqlConnection conn = new SqlConnection(connstr))
            //{
            //    conn.Open();
            //    using (var tx = conn.BeginTransaction())
            //    {
            //        try
            //        {
            //            Console.WriteLine("开始查询");
            //            using (var selectCmd = conn.CreateCommand())
            //            {
            //                selectCmd.Transaction = tx;
            //                selectCmd.CommandText = "select * from T_Grils with(xlock,ROWLOCK) where id=1";
            //                using (var reader = selectCmd.ExecuteReader())
            //                {
            //                    if (!reader.Read())
            //                    {
            //                        Console.WriteLine("没有id为1的女孩");
            //                        return;
            //                    }
            //                    string bf = null;
            //                    if (!reader.IsDBNull(reader.GetOrdinal("BF")))
            //                    {
            //                        bf = reader.GetString(reader.GetOrdinal("BF"));
            //                    }

            //                    if (!string.IsNullOrEmpty(bf)) // 已经有男朋友了
            //                    {
            //                        if (bf == myname)
            //                        {
            //                            Console.WriteLine("早已经是我的人了");
            //                        }
            //                        else
            //                        {
            //                            Console.WriteLine($"早已经被{bf}抢走了");
            //                        }
            //                        Console.ReadKey();
            //                        return;
            //                    }
            //                    // 如果bf==null,则继续向下抢
            //                }
            //                Console.WriteLine("查询完成,开始update");
            //                using (var updateCmd = conn.CreateCommand())
            //                {
            //                    updateCmd.Transaction = tx;
            //                    updateCmd.CommandText = "Update T_Grils set BF=@bf where id=1";
            //                    updateCmd.Parameters.Add(new SqlParameter("@bf", myname));
            //                    updateCmd.ExecuteNonQuery();
            //                }
            //                Console.WriteLine("结束Update");
            //                Console.WriteLine("按任意键结束事务");
            //                Console.ReadKey();
            //            }
            //            tx.Commit();
            //        }
            //        catch (Exception ex)
            //        {
            //            Console.WriteLine(ex);
            //            tx.Rollback();
            //        }
            //    }
            //}

            //Console.ReadKey();


            string connstr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;

            using (SqlConnection conn = new SqlConnection(connstr))
            {
                conn.Open();
                using (var tx = conn.BeginTransaction())
                {
                    try
                    {
                        long id = 0;
                        Console.WriteLine("开始查询");
                        using (var selectCmd = conn.CreateCommand())
                        {
                            selectCmd.Transaction = tx;
                            selectCmd.CommandText = "select top 1 id,Name from T_Grils with(UPDLOCK,READPAST) where status=0";
                            using (var reader=selectCmd.ExecuteReader())
                            {
                                if (reader.Read())
                                {
                                    id = long.Parse(reader["id"].ToString());
                                    Console.WriteLine(reader["Name"]);
                                }
                            }
                        }

                        using (var updateCmd=conn.CreateCommand())
                        {
                            updateCmd.Transaction = tx;
                            updateCmd.CommandText = "update T_Grils set status=1 where id=@id";
                            updateCmd.Parameters.Add(new SqlParameter("@id", id));
                            updateCmd.ExecuteNonQuery();
                        }

                        Thread.Sleep(20 * 1000);
                            
                        tx.Commit();
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex);
                        tx.Rollback();
                    }
                }
            }

            Console.ReadKey();

        }
    }
}
